import {DragSource} from "./DragSource";
import {DropTarget} from "./DropTarget";
import GestureDetector from "../utils/GestureDetector";
import {DragShadow} from "./DragShadow";

/**
 *  拖拽操作控制辅助类.
 */
export class DragDropHelper {

    // private dragSources: DragSource[] = [];
    private dropTargets: DropTarget[] = [];

    private currentSource: DragSource = null;
    private currentHoverTarget: DropTarget = null;
    private gesture: GestureDetector = null;
    private readonly dragShadow: DragShadow = null;
    private dragState: number = 0;// 0=未开始拖拽, 1=正在拖拽中.
    constructor(boundNode: cc.Node, dragShadow: DragShadow) {
        this.dragShadow = dragShadow;
        this.gesture = new GestureDetector(boundNode);
        this.gesture.onDrag((p, d) => {
            if (!this.dragState) {
                return;
            }
            if (this.dragShadow) {
                this.dragShadow.onDrag(p, d);
            }
            this.onDrag(p, d);
        });
        this.gesture.onEndTouch((p) => {
            if (!this.dragState) {
                return;
            }
            if (this.dragShadow) {
                this.dragShadow.onDragEnd();
            }
            this.onDragEnd(p);
        });
    }

    public addDropTarget(target: DropTarget) {
        if (this.dropTargets.indexOf(target) == -1) {
            this.dropTargets.push(target);
        }
    }

    public removeDropTarget(target: DropTarget) {
        const index = this.dropTargets.indexOf(target);
        if (index >= 0) {
            this.dropTargets.splice(index, 1);
        }
    }

    // 开始拖拽.
    public startDrag(source: DragSource) {
        this.currentSource = source;
        this.dragState = 1;
        if (this.dragShadow) {
            this.dragShadow.onDragStart(this.currentSource);
        }
        this.currentSource.onDragStart();
    }

    public reset() {
        this.currentSource = null;
        this.currentHoverTarget = null;
        this.dragState = 0;
        this.dragShadow.hide();
    }

    private onDrag(pos: cc.Vec2, delta: cc.Vec2) {
        if (!this.currentSource) {
            return;
        }
        for (let target of this.dropTargets) {
            if (target.checkBound(pos)) {
                // 如果拖拽的源和目标相同的话,直接返回.
                // @ts-ignore
                if (this.currentSource === target) {
                    break;
                }
                if (this.currentHoverTarget != target) {
                    if (this.currentHoverTarget) {
                        // 上一个目标执行leave操作
                        this.currentHoverTarget.onLeave(this.currentSource)
                    }
                    target.onHover(this.currentSource);
                    this.currentHoverTarget = target;
                }
                break
            } else if (this.currentHoverTarget == target) {
                this.currentHoverTarget.onLeave(this.currentSource);
                this.currentHoverTarget = null;
            }
        }
    }

    private onDragEnd(p: cc.Vec2) {
        if (!this.currentSource) {
            return;
        }
        this.dragState = 0;
        let ret = false;
        for (let target of this.dropTargets) {
            if (target.checkBound(p)) {
                target.onDrop(this.currentSource);
                this.currentSource.onDragEnd({target});
                break;
            }
        }
        if (!ret) {
            this.currentSource.onDragEnd({});
        }
    }
}
